// +build playground

package uci

import (
	"bufio"
	pos "code.google.com/p/gochess/position"
	"code.google.com/p/gochess/search"
	stats "code.google.com/p/gochess/statistics"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)

// this is the first version of the uci engine.
// its perfomance is superior to StartEngine()
// but its design is bad
func startEngineOldScool(in io.Reader, o, logger io.Writer) {

	out := &outWriter{out: o, log: logger}
	var p *pos.Position

	var duration time.Duration
	var depth int32
	var flags uint32
	ttsize := search.TTDefaultSize
	gui, info, ctrl := make(chan string), make(chan string), make(chan string)
	searching, shutdown := false, false

	go listenToGui(bufio.NewReader(in), gui)

	for {
		select {
		case line := <-gui:
			fmt.Fprint(logger, "> ", line)
			cmd, params, err := parseCommandline(line)
			if err != nil {
				continue
			}
			switch cmd {
			case "uci":
				fmt.Fprint(out, uciResponse)
			case "debug": // ignore
			case "isready":
				fmt.Fprintln(out, `readyok`)
			case "setoption":
				if searching || shutdown {
					continue
				}
				name, value, err := parseSetoption(params)
				if err != nil {
					return
				}
				switch name {
				case "Hash":
					size, err := strconv.Atoi(value)
					if err == nil && size >= 1 && size <= 2048 {
						ttsize = size
						search.Transpositions.Resize(size)
					}
				}
				_ = ttsize
				// todo
			case "register": // ignore
			case "ucinewgame":
				if !searching && !shutdown {
					search.Transpositions.Clear()
				}
			case "position":
				if !searching && !shutdown {
					p, err = parsePosition(params)
					if err != nil {
						fmt.Fprintln(logger, `error returned from uci.parsePosition():`, err)
					}
				}
			case "go":
				if searching || shutdown {
					continue
				}
				skip := false
				depth = 0
				duration = 0
				switch {
				case strings.HasPrefix(params, "ponder"): // ignore for now
					skip = true
				case strings.HasPrefix(params, "infinite"): // nothing to do
				case strings.HasPrefix(params, "searchmoves"): // todo:
				default:
					// only left: key-value pairs with integer values
					params, err := parseDigitParams(params)
					if err != nil {
						continue
					}
					for i := range params {
						switch value := params[i].value; params[i].key {
						case "depth":
							depth = value
						case "movetime":
							// todo: go routine, which sleeps x msec and
							// sends "stop" to ctrl (no, as this goroutine would stay
							// around even the search was "stop"ped)
							duration = time.Duration(value) * time.Millisecond
						case "wtime":
							if p.SideToMove() == pos.White {
								duration = time.Duration(value) * time.Millisecond / 25
							}
						case "btime":
							if p.SideToMove() == pos.Black {
								duration = time.Duration(value) * time.Millisecond / 25
							}
						case "winc": // todo
						case "binc": // todo
						case "nodes": // todo
						case "mate": // todo
						case "movestogo": // ignore for now
						default:
							continue
						}
					}
				}
				if !skip {
					searching = true
					stats.ClearStatistics()
					stats.StartTimer()
					go search.RunUCISearch1(p, pos.NoMove, duration, depth, flags, ctrl, info)
				}
			case "stop":
				if searching && !shutdown {
					shutdown = true
					ctrl <- "stop"
				}
			case "ponderhit": // ignore for now
			case "quit":
				if searching && !shutdown {
					shutdown = true
					stats.StopTimer()
					ctrl <- "stop"
				}
				return
			default: // ignore
			}
		case line := <-info:
			if strings.Contains(line, "bestmove") {
				shutdown = false
				searching = false
				stats.StopTimer()
			}
			fmt.Fprintln(out, line)
		}
	}
}
